package cmpe451.group7.ourcity.dao.impl;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.Subqueries;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import cmpe451.group7.ourcity.dao.TagSimilarityDAO;
import cmpe451.group7.ourcity.entity.Tag;
import cmpe451.group7.ourcity.entity.TagSimilarity;

@Repository("tagSimilarityDAO")
public class TagSimilarityDAOImpl extends GenericDAOImpl<TagSimilarity>
		implements TagSimilarityDAO {

	private static final long serialVersionUID = 1L;

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public List<TagSimilarity> findAll() {
		return super.findAll(TagSimilarity.class);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public TagSimilarity findByID(long id) {
		return super.findByID(TagSimilarity.class, id);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public boolean hasSimilarity(Tag tag) {
		Session session = getCurrentSession();
		int count = ((Number) session.createCriteria(TagSimilarity.class)
				.add(Restrictions.eq("tag1_mID", tag.getmID()))
				.setProjection(Projections.rowCount()).uniqueResult())
				.intValue();
		return count > 0;
	}

	@Override
	@SuppressWarnings("unchecked")
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public List<TagSimilarity> findByMID1(String mid1) {
		if (StringUtils.isEmpty(mid1))
			return null;

		Session session = getCurrentSession();
		List<TagSimilarity> list = session.createCriteria(TagSimilarity.class)
				.add(Restrictions.eq("tag1_mID", mid1))
				.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();

		return list;
	}

	@Override
	@SuppressWarnings("unchecked")
	@Transactional
	public List<Tag> getAllSimilarTags(List<Tag> tags) {
		if (CollectionUtils.isEmpty(tags))
			return null;

		List<String> mids = new ArrayList<String>();
		for (Tag t : tags)
			mids.add(t.getmID());

		Session session = getCurrentSession();

		// "SELECT t FROM Tag t WHERE t.mID IN (SELECT ts.tag2_mID FROM TagSimilarity ts WHERE ts.tag1_mID IN (:mid_list))";
		DetachedCriteria subquery = DetachedCriteria
				.forClass(TagSimilarity.class)
				.setProjection(Projections.property("tag2_mID"))
				.add(Restrictions.in("tag1_mID", mids));
		
		Criteria criteria = session.createCriteria(Tag.class).add(
				Subqueries.propertyIn("mID", subquery));

		List<Tag> list = criteria.list();
		return list;
	}

	public static void main(String[] args) {
		List<String> l = new ArrayList<String>();
		l.add("ali");
		l.add("veli");

		System.out.println(StringUtils.join(l, ", "));
	}
}
